package com.java.basis.thread.cas;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @author wangning
 * @create 2022-01-28 10:38
 */
public class TestAccount {
	public static void main(String[] args) {
//		AccountUnsafe accountUnsafe = new AccountUnsafe(10000);
//		Account.demo(accountUnsafe);
		AccountCAS accountCAS = new AccountCAS(10001);
		Account.demo(accountCAS);

	}
}

class AccountCAS implements Account {
	private AtomicInteger balance;

	public AccountCAS(int balance) {
		this.balance = new AtomicInteger(balance);
	}

	@Override
	public Integer getBalance() {
		return balance.get();
	}

	@Override
	public void withdraw(Integer amount) {
//		while (true) {
//			//获取余额的最新值
//			int prev = balance.get();
//			//要修改的余额
//			int next = prev - amount;
//			//希望把要修改的余额同步到主存上去
//			if(balance.compareAndSet(prev, next)) {
//				break;
//			}
//		}
		balance.getAndAdd(-1 * amount);
	}
}

class AccountUnsafe implements Account {

	private Integer balance;

	public AccountUnsafe(Integer balance) {
		this.balance = balance;
	}

	@Override
	public Integer getBalance() {
		synchronized (this) {
			return this.balance;
		}
	}

	@Override
	public void withdraw(Integer amount) {
		synchronized (this) {
			this.balance -= amount;
		}
	}
}

interface Account {
	//获取余额
	Integer getBalance();

	//取款
	void withdraw(Integer amount);

	/**
	 * 方法内启动1000个 线程，每个线程做-10元操作
	 * 如果初始余额为10000.那么正确的结果就是0
	 */
	static void demo(Account account) {
		List<Thread> ts = new ArrayList<>();
		for (int i = 0; i < 1000; i++) {
			ts.add(new Thread(() -> {
				account.withdraw(10);
			}));
		}
		long start = System.nanoTime();
		ts.forEach(Thread::start);
		ts.forEach(t -> {
			try {
				t.join();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		});
		long end = System.nanoTime();
		System.out.println(account.getBalance() + "元 cost: " + (end-start)/1000_000 + "ms");

	}
}
